package com.bauer.java.spring.transaction.declarative;

import com.bauer.java.spring.transaction.mapper.BaseMenuMapper;
import com.bauer.java.spring.transaction.model.po.BaseMenu;
import com.bauer.java.spring.transaction.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * @Author ：rui.wei
 * @Date ：Created in 11:11 2019/7/4
 * @Description：
 *
 * 声明式事物   通过spring aop实现（或者aspectj  ）
 *
 *  spring aop 是运行时生成代理类
 *  aspectj 也是在运行时在目标类中织入代码
 *
 *
 */
@Component
public class DeclarativeTransactionDemo {

    @Autowired
    private BaseMenuMapper baseMenuMapper;

    @Autowired
    private UserService userService;


    /**
     * 未添加transactional 注解
     *
     * 若在 insert之后抛出异常等情况   数据还是会保存到数据库中的
     */
    public void withTransaction() {
        BaseMenu baseMenu = new BaseMenu();
        baseMenu.setMenuName("menu1");
        baseMenuMapper.insert(baseMenu);
        //这时事物已提交 数据已经可以在数据库中查看到
        System.out.println("menu saved");
    }


    /**
     * （一）注解式声明事物
     * 开启声明式事物的步骤
     *
     * 1、创建dataSourceTransactionManager bean  (也可以是hibernate jta 等等其他的transactionManager)  最常用
     * 2、设置<tx:annotation txManager="txManager">
     * 3、在需要添加事物的方法或者类上添加@Transactional注解
     *
     *
     *  添加Transactional  开启声明式事物
     *  rorollbackFor 阿里规范规定指明回滚异常   回滚的异常包含其子类
     *      默认条件下回滚的异常为RuntimeException  或者Error （及其子类）  下为文档中描述
     *      by default,a transaction will be rolling back on {@link RuntimeException}
     * 	    and {@link Error} but not on checked exceptions (business exceptions)
     *
     *  propagation 事物的传播类型
     * @see Propagation
     *      REQUIRED  若当前存在事物 加入当前事物中  若不存在  则创建新的事物
     *      SUPPORTS   存在加入当前事物  不存在  不开启事物
     *      MANDATORY  存在则加入当前事物  不存在怎抛出异常
     *      REQUIRES_NEW 创建新的事物  若当前事物存在则挂起
     *      NOT_SUPPORTED 不创建事物  若当前存在事物则挂起
     *      NEVER  不使用事物 当前存在时抛出异常
     *      NESTED 若当前存在事物 加入当前事物中   若不存在则创建新的事物  行为和REQUIRED类似
     *
     *
     *
     *
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void defaultTransaction() {
        BaseMenu baseMenu = new BaseMenu();
        baseMenu.setMenuName("menu1");
        baseMenu.setGmtCreate(new Date());
        baseMenuMapper.insert(baseMenu);
        System.out.println("menu saved");
    }

    public void useTransactionSupports() {
        BaseMenu baseMenu = new BaseMenu();
        baseMenu.setMenuName("menu2");
        baseMenu.setGmtCreate(new Date());
        baseMenuMapper.insert(baseMenu);
        userService.updateMenu();
    }




}
